package com.zh.fileupload.controller;

import com.zh.fileupload.config.ServerConfig;
import com.zh.fileupload.entity.R;
import com.zh.fileupload.util.UUIDUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 文件上传与下载
 */
@RestController
@RequestMapping("/common")
public class CommonController {
    /**
     * 存储上传文件的目录路径
     */
    @Value("${upload.path}")
    private String baseDir;

    /**
     * 服务端配置
     */
    @Autowired
    private ServerConfig serverConfig;

    /**
     * 上传文件
     * MultipartFile：SpringMVC获取前端的输入文件流，封装的文件解析对象
     * file：是 MultipartFile 对象参数的变量名（参数名），这个名字必须与前端传递的文件参数一致！，这里就是file
     */
    @PostMapping("/upload")
    public R<Map<String, String>> upload(MultipartFile file) throws IOException {
        //判断上传目录是否存在，不存在则创建
        File fileDir = new File(baseDir);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }
        //获取上传的原始文件名
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null) {
            originalFilename = "";
        }
        //获取拓展名，截取最后一个.后面的字符串，就是拓展名
        String extName = originalFilename.substring(originalFilename.lastIndexOf("."));
        //直接使用原始文件名，会导致相同文件名的图片会覆盖，所以添加UUID作为文件夹
        String fileName = UUIDUtils.getUUID() + extName;
        //存储到服务器上
        file.transferTo(new File(fileDir, fileName));

        //构造访问文件Url，并返回
        String fileUrl = serverConfig.getUrl() + "/common/download?name=" + fileName;
        Map<String, String> resultMap = new HashMap<>();
        resultMap.put("url", fileUrl);
        return R.success(resultMap);
    }

    /**
     * 文件下载
     * 注意：方法返回值为void，而不是R，因为响应的是一个图片文件流，而不是json
     *
     * @param name     需要下载的文件名
     * @param response 响应对象，用于输出文件流给客户端
     */
    @GetMapping("/download")
    public void download(String name, HttpServletResponse response) throws IOException {
        //文件
        File file = new File(baseDir + name);
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        ServletOutputStream out = response.getOutputStream();

        //原生IO流实现
        //输出文件到响应中
        byte[] buf = new byte[1024];
        int length;
        while ((length = bis.read(buf)) != -1) {
            out.write(buf, 0, length);
        }
        out.flush();
        //关闭资源，ServletOutputStream out 响应输出流不需要关闭，Tomcat会帮我们关闭
        bis.close();

        //使用工具类实现
        //IOUtils.copy(fis, out);
    }
}